package com.hobart.learning.lagou.edu.factory;

import com.hobart.learning.lagou.edu.annotation.Autowired;
import com.hobart.learning.lagou.edu.annotation.Component;
import com.hobart.learning.lagou.edu.utils.TransactionManager;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author: Hobart Mr.Bai
 * @create: 2021-02-03 09:47
 * @description: 代理 事务管理
 * @Version 1.0
 **/
@Component
public class ProxyFactory {

    // 第三版
//    private TransactionManager transactionManager;
//
//    public void setTransactionManager(TransactionManager transactionManager) {
//        this.transactionManager = transactionManager;
//    }

    @Autowired
    private TransactionManager transactionManager;

//    private ProxyFactory() { }
//
//    private static ProxyFactory proxyFactory = new ProxyFactory();
//
//    public static ProxyFactory getInstance() {
//        return proxyFactory;
//    }

    // JDK 代理
    public Object getJDKProxy(Object obj){
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
                obj.getClass().getInterfaces(),
                (Object proxy, Method method, Object[] args) -> {
                    Object result = null;
                    try {
                        transactionManager.beginTransaction();
                        result = method.invoke(obj, args);
                        transactionManager.commitTransaction();
                    } catch (Exception e) {
                        e.printStackTrace();
                        transactionManager.rollbackTransaction();
                        throw e;
                    }
                    return result;
                });
    }

    public Object getCGLibProxy(Object obj) {

        return Enhancer.create(obj.getClass(), new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                Object result = null;
                try {
                    transactionManager.beginTransaction();
                    result = method.invoke(obj, objects);
                    transactionManager.commitTransaction();
                } catch (Exception e) {
                    e.printStackTrace();
                    transactionManager.rollbackTransaction();
                    throw e;
                }
                return result;
            }
        });

    }
}
